package NG::Chat::Http;
use strict;
use warnings;
use utf8;

use NG::Sys::Sock qw(
InetListen CreateListener
SendMessage PrepareSendMessage SendMessagePrepared
);
use NG::Chat::Message qw(HttpParse HttpMessage);

my $con_count = 1;
my %con_all;

sub Create {
	my ($addr,$port,$process) = @_;
	my $http = InetListen($addr,$port);
	
	my $on_message = sub {
		my ($waiter,$message) = @_;
		if($message->{error}){
			unless(int($message->{error}/100) == 5){
				return send_message($waiter->fh,$message);
			}else{
				warn $message->{text};
			}
		}
		elsif($message = $process->($message,$waiter->fh,\&send_message)){
			return send_message($waiter->fh,$message);
		}
		getClose($waiter);
	};

	return CreateListener($http,\&getConnect,\&HttpParse,$on_message,\&getClose,\&getError);
}
sub CreatePrepared {
	my ($addr,$port,$process) = @_;
	my $http = InetListen($addr,$port);
	
	my $writer = PrepareSendMessage(\&getClose,\&getDone);

	my $sender = sub {
		my ($fh,$msg) = @_;
		my $message = HttpMessage($msg);
		my $waiter = SendMessagePrepared($fh,$message,$writer);
		$con_all{++$con_count} = $waiter;
		$waiter->data->[1] = $con_count;
	};
	
	my $on_message = sub {
		my ($waiter,$message) = @_;
		if($message->{error}){
			unless(int($message->{error}/100) == 5){
				return $sender->($waiter->fh,$message);
			}else{
				warn $message->{text};
			}
		}
		elsif($message = $process->($message,$waiter->fh,$sender)){
			return $sender->($waiter->fh,$message);
		}
		getClose($waiter);
	};

	return CreateListener($http,\&getConnect,\&HttpParse,$on_message,\&getClose,\&getError);
}

sub getConnect {
	my $waiter = shift;
	$con_all{++$con_count} = $waiter;
	$waiter->data->[1] = $con_count;
}
sub send_message {
	my ($fh,$msg) = @_;
	my $message = HttpMessage($msg);
	my $waiter = SendMessage($fh,$message,\&getClose,\&getDone);
	$con_all{++$con_count} = $waiter;
	$waiter->data->[1] = $con_count;
}
sub getClose {
	my $waiter = shift;
	my $con = $waiter->data->[1];
	delete $con_all{$con} if defined $con;
}
sub getDone {
	my $waiter = shift;
	my $con = $waiter->data->[1];
	delete $con_all{$con} if defined $con;
	$waiter->fh->close;
}
sub getError {
	my ($waiter,$errmsg) = @_;
	warn $errmsg;
}


1;
